#pragma once
#include <iostream>
#include <queue>
#include <vector>
#include <functional>
#include <string>
#include "Log.hpp"
#include "Thread.hpp"
#include "LockGuard.hpp"

using namespace std;

const int defaultnum = 5;

class ThreadData
{
public:
    ThreadData(const string &name) : threadname(name)
    {
    }
    ~ThreadData()
    {
    }

public:
    const string threadname;
};

template <class T>
class ThreadPool
{
private:
    ThreadPool(int thread_num = defaultnum) : _thread_num(thread_num)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);

        // 构建若干个线程

        for (int i = 0; i < _thread_num; i++)
        {
            // 待优化
            string threadname = "thread-";
            threadname += to_string(i + 1);

            ThreadData td(threadname);
            // 把方法绑给了线程
            //  Thread<ThreadData> t(threadname,
            //           bind(&ThreadPool<T>::ThreadRun,this,placeholders::_1),
            //          td);

            // _threads.push_back(t);

            _threads.emplace_back(threadname,
                                  bind(&ThreadPool<T>::ThreadRun, this,
                                       placeholders::_1),
                                  td);
            lg.LogMessage(Info, "%s is created ...\n", threadname.c_str());
        }
    }
    ThreadPool(const ThreadPool<T> &tp) = delete;
    const ThreadPool<T> &operator=(const ThreadPool<T>) = delete;

public:
    static ThreadPool<T> *GetInstance()
    {
        if (instance == nullptr)//双if判断的方式，来对后来的线程拦截（不用再进来申请锁判断了）
        {
            LockGuard lockguard(&sig_lock);

            if (instance == nullptr)
            {
                lg.LogMessage(Info,"创建单例成功...\n");
                instance = new ThreadPool<T>();
            }
        }

        return instance;
    }

    void checkSelf()
    {
        // 如果任务多了线程少了那么需要增加线程
        if (_task_num >= _task_water_high && _thread_num < _thread_water_high)
        {
            for (int i = _thread_num; i <= _thread_water_high; i++)
            {
                // 待优化
                string threadname = "thread-";
                threadname += to_string(i + 1);

                ThreadData td(threadname);
                _threads.emplace_back(threadname,
                                      bind(&ThreadPool<T>::ThreadRun, this,
                                           placeholders::_1),
                                      td);
                lg.LogMessage(Info, "%s is created ...\n", threadname.c_str());
            }
            _thread_num = _thread_water_high;
        }

        // 如果线程多了任务少了减少线程
        if (_task_num < _task_water_low && _thread_num > _thread_water_high)
        {
            Wait();
        }
    }
    bool Start()
    {
        // 启动线程
        for (auto &thread : _threads)
        {
            thread.Start(); // 执行初始化时的函数
            lg.LogMessage(Info, "%s is running ...\n", thread.Threadname().c_str());
        }

        return true;
    }
    void ThreadWakeup()
    {
        pthread_cond_signal(&_cond); // 唤醒cond队列中阻塞的一个线程
    }

    void ThreadWait(const ThreadData &td)
    {
        lg.LogMessage(Debug, "no task,%s is sleeping ...\n", td.threadname.c_str());

        pthread_cond_wait(&_cond, &_mutex); // 进行线程等待
    }

    // 线程执行的方法
    void ThreadRun(ThreadData &td)
    {
        while (true)
        {
            sleep(1);
            checkSelf();
            T t;
            {
                // 取任务
                LockGuard lockguard(&_mutex);
                while (_q.empty()) // 若为空则进行等待
                {
                    ThreadWait(td); // 不断等待直到队列不为空为止
                }
                // 出来后表示此时队列中有数据，对此就需要
                // 进行取出并处理
                lg.LogMessage(Debug, "thread %s is wakeup\n", td.threadname.c_str());
                t = _q.front();
                _q.pop();
            }
            // 处理任务
            // 他属于一个线程私有，所以可以不加锁
            t(); // 调用任务的仿函数
            // lg.LogMessage(Debug, "%s handler task %s done,result is: %s\n", td.threadname.c_str(), t.PrintTask().c_str(), t.PrintResult().c_str());
        }
    }

    void Push(T &in)
    {
        sleep(1);
        LockGuard lockguard(&_mutex);
        _q.push(in);
        ThreadWakeup();
    }

    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
    }

    // 用来进行测试的
    void Wait()
    {
        for (auto &thread : _threads)
        {
            thread.Join(); // 执行初始化时的函数！！
        }
    }

private:
    queue<T> _q;
    vector<Thread<ThreadData>> _threads;

    static ThreadPool<T> *instance;
    int _thread_num;
    int _task_num;

    int _task_water_low;
    int _task_water_high;
    int _thread_water_low;
    int _thread_water_high;

    pthread_mutex_t _mutex;
    static pthread_mutex_t sig_lock;
    pthread_cond_t _cond;
};

template <class T>
ThreadPool<T> *ThreadPool<T>::instance = nullptr;
template <class T>
pthread_mutex_t ThreadPool<T>::sig_lock = PTHREAD_MUTEX_INITIALIZER;
// pthread_mutex_initializer